#include "Texture.h"
#include "..\dxstdafx.h"
#include "..\utils\Log.h"

namespace ds {

Texture::Texture(const char* handle) : Asset(handle) , texture(NULL) , wrap(false) { }

Texture::Texture(const char* handle,LPDIRECT3DTEXTURE9 texture,int width,int height) : Asset (handle) {
	this->texture = texture;	
	info.Width = width;
	info.Height = height;
	wrap = false;
}

Texture::~Texture() {
	LOGC(logINFO,"Texture") << "Removing texture " << getName();
	SAFE_RELEASE(texture);			
}

bool Texture::loadTexture(const char* fileName,int width,int height) {
	return loadTexture(fileName);
}

bool Texture::loadTexture(const char* fileName) {
	IDirect3DDevice9 * pDevice = gEngine->getDevice();
    int lw = D3DX_DEFAULT;
	int lh = D3DX_DEFAULT;	
	LOGC(logINFO,"Texture") << "Texture " << fileName << " not found in ResourceManager - loading now";
	D3DXIMAGE_INFO imageInfo;
	
	HR(D3DXCreateTextureFromFileEx(pDevice, //device
		fileName,        //file name
		0,//D3DX_DEFAULT,//lw,      //width
        0,//D3DX_DEFAULT,//lh,      //height
        1,//D3DX_DEFAULT,      //mip levels
        0,              //usage
        D3DFMT_UNKNOWN,    //texture color format
        D3DPOOL_MANAGED,   //memory class
        D3DX_FILTER_NONE, //D3DX_DEFAULT     //filter
        D3DX_DEFAULT,      //mip filter
        0x000000,        //color key
        &imageInfo,              //source info
        NULL,              //pallette
		&texture));    //texture object							
	
	info.Width = imageInfo.Width;
	info.Height = imageInfo.Height;		
	LOGC(logINFO,"Texture") << "Width: " << info.Width << " Height: " << info.Height << " mip levels " << imageInfo.MipLevels << " Format: " << imageInfo.Format;
	return true;
}

bool Texture::loadTextureFromResource(LPCTSTR resourceID) {
	IDirect3DDevice9 * pDevice = gEngine->getDevice();
    int lw = D3DX_DEFAULT;
	int lh = D3DX_DEFAULT;
	info.Width = lw;
	info.Height = lh;
	HR(D3DXCreateTextureFromResource(pDevice, NULL,resourceID, &texture));
	D3DSURFACE_DESC desc;
	texture->GetLevelDesc(0,&desc);
	info.Width = desc.Width;
	info.Height = desc.Height;				
	return true;
}

bool Texture::createTexture(int width,int height) {
	//SAFE_RELEASE(texture);
	HR(gEngine->getDevice()->CreateTexture( width, height,1, 0,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,&texture,NULL ));
	info.Width = width;
	info.Height = height;
	info.Format = D3DFMT_A8R8G8B8;
	// clear the texture with white color		
	D3DLOCKED_RECT sRect;
	texture->LockRect(0, &sRect, NULL, NULL);
	BYTE *bytes = (BYTE*)sRect.pBits;
	memset(bytes, 128, info.Width*sRect.Pitch);
	texture->UnlockRect(0);
	return true;
}

bool Texture::createTexture(char* data,UINT size) {
	HR(D3DXCreateTextureFromFileInMemory(gEngine->getDevice(),data,size,&texture));	
	return true;
}

LPDIRECT3DTEXTURE9 Texture::getTexture() {
	return texture;
}

int Texture::getWidth() {
	return info.Width;
}

int Texture::getHeight() {
	return info.Height;
}

RECT Texture::getBounds() {
	RECT rect = {0, 0, getWidth()-1, getHeight()-1};
	return rect;
}

void Texture::lock() {
	ZeroMemory(&lockedRect, sizeof(lockedRect));
	HR(texture->LockRect(0,&lockedRect,NULL,0));	
}

void Texture::setColor(int x,int y,uchar r,uchar g,uchar b,uchar a) {
	uchar * pBits = (uchar *)lockedRect.pBits;
	int p = (x+y*info.Height)*4;
	pBits[p]   = b;//*255;   // blue			
	pBits[p+1] = g;//*255;  // green				
	pBits[p+2] = r;//*255;      // red
	pBits[p+3] = a;//*255;
}

void Texture::setColor(int x,int y,int offset,uchar value) {
	uchar * pBits = (uchar *)lockedRect.pBits;
	pBits[(x+y*info.Height)*4+offset] = value;
}

uchar Texture::getColor(int x,int y,int offset) {
	uchar * pBits = (uchar *)lockedRect.pBits;
	return (uchar)pBits[(x+y*info.Height)*4+offset];	
}

Color Texture::getColor(int x,int y) {
	uchar * pBits = (uchar *)lockedRect.pBits;
	uchar b = (uchar)pBits[(x+y*info.Height)*4];	
	uchar g = (uchar)pBits[(x+y*info.Height)*4+1];	
	uchar r = (uchar)pBits[(x+y*info.Height)*4+2];	
	uchar a = (uchar)pBits[(x+y*info.Height)*4+3];	
	return Color(r,g,b,a);
}

void Texture::unlock() {
	HR(texture->UnlockRect(0));	
}

};
